package com.hmall.item.es;

import cn.hutool.json.JSONUtil;
import com.hmall.item.domain.dto.ItemDoc;
import org.apache.http.HttpHost;
import org.apache.lucene.search.TotalHits;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.util.List;
import java.util.Map;

public class ElesticSearchText {


    private RestHighLevelClient client;

    @Test
    public void testSearch() throws IOException {
        //1、创建request对象
        SearchRequest request = new SearchRequest("market");
        //2、配置request参数
        request.source()
                .query(QueryBuilders.matchAllQuery());
        //3、发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4、解析结果
//        SearchHits searchHits = response.getHits();
//        //4.1、总条数
//        searchHits.getTotalHits();
//        //4.2、命中的数据
//        SearchHit[] hits = searchHits.getHits();
//        for (SearchHit hit : hits) {
//            //4.2.1、获取source结果
//            String json = hit.getSourceAsString();
//            //4.2.2、转换为ItemDoc对象
//            ItemDoc doc = JSONUtil.toBean(json, ItemDoc.class);
//        }
        //
        parseResponseResult(response);
    }

    //复合查询
    @Test
    public void testComplexitySearch() throws IOException {
        //1、创建request对象
        SearchRequest request = new SearchRequest("market");
        //2、配置request参数
        request.source().query(
                QueryBuilders.boolQuery()
                        //must添加匹配项 必须匹配
                        .must(QueryBuilders.matchQuery("name", "脱脂牛奶"))
                        //filter添加过滤项 不影响must
                        .filter(QueryBuilders.termQuery("brand.keyword","德亚"))
                        //如果有多个子查询，重复调用就行，底层会自动合并，不会覆盖
                         //range添加范围过滤
                        .filter(QueryBuilders.rangeQuery("price").lt(30000))
                );
        //3、发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4、解析结果
        parseResponseResult(response);
    }

    //排序和分页
    @Test
    public void testdSortAndPageSearch() throws IOException {
        int pageNo = 1, pageSize = 5;
        //1、创建request对象
        SearchRequest request = new SearchRequest("market");
        //2、配置request参数
        request.source()
                .query(QueryBuilders.matchAllQuery())
                .from((pageNo - 1) * pageSize).size(pageSize)
                .sort("sold", SortOrder.DESC)
                .sort("price", SortOrder.ASC);
        //3、发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4、解析结果
        parseResponseResult(response);
    }

    //高亮
    @Test
    public void testdHighlighterSearch() throws IOException {
        int pageNo = 1, pageSize = 5;
        //1、创建request对象
        SearchRequest request = new SearchRequest("market");
        //2、配置request参数
        request.source()
                //匹配查询Query查询
                .query(QueryBuilders.matchQuery("name", "脱脂牛奶"))
                //高亮条件
                .highlighter(
                SearchSourceBuilder.highlight()
                        .field("name")
                        .preTags("<em>")
                        .postTags("</em>")
        );
        //3、发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4、解析结果
        parseResponseResult(response);
    }

    //解析结果
    public static void parseResponseResult(SearchResponse response){
        //4、解析结果
        SearchHits searchHits = response.getHits();
        //4.1、总条数
        TotalHits totalHits = searchHits.getTotalHits();
        System.out.println("总条数："+totalHits.value);
        //4.2、命中的数据
        SearchHit[] hits = searchHits.getHits();
        for (SearchHit hit : hits) {
            //4.2.1、获取source结果
            String json = hit.getSourceAsString();
            //4.2.2、转换为ItemDoc对象
            ItemDoc doc = JSONUtil.toBean(json, ItemDoc.class);
//            System.out.println(doc);
            //4.2.3、获取高亮结果
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            if (!highlightFields.isEmpty() && highlightFields != null){
                HighlightField name = highlightFields.get("name");
                String newName = name.getFragments()[0].toString();
                doc.setName(newName);
            }
            System.out.println(doc);
        }
    }



    @Test
    public void testAggs() throws IOException {
        //1、创建请求
        SearchRequest request = new SearchRequest();

        // 2.准备请求参数
        BoolQueryBuilder bool = QueryBuilders.boolQuery()
                .filter(QueryBuilders.termQuery("category", "手机"))
                .filter(QueryBuilders.rangeQuery("price").gte(300000));
        request.source().query(bool).size(0);

        // 3.聚合参数
        request.source().aggregation(
                AggregationBuilders.terms("brand_agg").field("brand").size(5)
        );
        //2、添加参数
//        request.source().size(0);
//        request.source().aggregation(AggregationBuilders.terms("bard_agg").field("brand_keyword").size(10));

        //3、发送请求
        SearchResponse search = client.search(request, RequestOptions.DEFAULT);

        //4、处理结果
        Aggregations aggregations = search.getAggregations();
        Terms bardAgg = aggregations.get("bard_agg");
        List<? extends Terms.Bucket> buckets = bardAgg.getBuckets();
        for (Terms.Bucket bucket : buckets) {
            System.out.println("brand:" + bucket.getKeyAsString());
            System.out.println("count:" + bucket.getDocCount());
        }
    }



    @BeforeEach
// 在每个测试方法之前执行
    void setUp() {
        // 创建客户端
        this.client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.253.130:9200")
        ));
    }
    @AfterEach
// 在每个测试方法之后执行
    void tearDown() throws IOException {
        // 关闭客户端
        this.client.close();
    }
}
